#include "VSAVObject.h"
#include "VSGraphicInclude.h"
#include "VSStream.h"
using namespace VSEngine2;
IMPLEMENT_RTTI_NoCreateFun(VSAVObject,VSCLObject)
IMPLEMENT_INITIAL_NO_CLASS_FACTORY_BEGIN(VSAVObject)
IMPLEMENT_INITIAL_NO_CLASS_FACTORY_END
BEGIN_ADD_PROPERTY(VSAVObject,VSCLObject)
REGISTER_PROPERTY(m_World,WorldTransform,VSProperty::F_SAVE_LOAD_CLONE);
REGISTER_PROPERTY(m_Local,LocalTransform,VSProperty::F_SAVE_LOAD_CLONE);
REGISTER_PROPERTY(m_pParent,Parent,VSProperty::F_SAVE_LOAD_CLONE);
END_ADD_PROPERTY
VSAVObject::~VSAVObject()
{

	m_pParent = NULL;

}
VSAVObject::VSAVObject()
{
	m_pParent = NULL;
}
unsigned int VSAVObject::DiskUse()const
{
	unsigned int Used = VSCLObject::DiskUse();
	Used += m_Local.DiskUse() + m_World.DiskUse();
	Used += sizeof(VSAVObject *);
	return Used;
}
bool VSAVObject::Save(VSStream & rStream,unsigned int &iSaveUse)const
{
	if(!VSCLObject::Save(rStream,iSaveUse))
		return 0;
	if(!m_World.Save(rStream,iSaveUse))
		return 0;
	if(!m_Local.Save(rStream,iSaveUse))
		return 0;

	if(!rStream.WriteObjectPtr(m_pParent))
		return 0;
	iSaveUse += sizeof(VSAVObject *);


	return 1;
}
bool VSAVObject::Load(VSStream & rStream,unsigned int &iSaveUse)
{
	if(!VSCLObject::Load(rStream,iSaveUse))
		return 0;
	if(!m_World.Load(rStream,iSaveUse))
		return 0;
	if(!m_Local.Load(rStream,iSaveUse))
		return 0;

	if(!rStream.ReadObjectPtr(m_pParent))
		return 0;
	iSaveUse += sizeof(VSAVObject *);


	return 1;
}
bool VSAVObject::Link(VSStream & rStream)
{
	if(!VSCLObject::Link(rStream))
		return 0;
	rStream.LinkObjectPtr(m_pParent);
	return 1;

}
bool VSAVObject::Clone(const VSObject *pObject,unsigned int uiType)
{
	const VSAVObject* Temp = DynamicCast<VSAVObject>(pObject); 
	if(!Temp)
		return 0;
	if(VSCLObject::Clone(pObject,uiType))
	{
		m_World = Temp->m_World;
		m_Local = Temp->m_Local;
		//m_pParent = Temp->m_pParent;

		return 1;
	}
	else
	{
		return 0;

	}
}
void VSAVObject::UpdateAll(double dAppTime)
{
	if (dAppTime > 0.0f)
	{
		UpdateController(dAppTime);
	}
	UpdateTransform(dAppTime);
	m_bIsChanged = false;
}
void VSAVObject::ForceUpdateTransform()
{
	VSAVObject * pParent = this;
	VSAVObject * pCur = NULL;
	while(pParent)
	{
		if (pParent->m_bIsChanged)
		{
			pCur = this;
		}
		pParent = pParent->GetParent();
	}
	if (pCur)
	{
		pCur->UpdateAll(0.0f);
	}

}

void VSAVObject::UpdateTransform(double dAppTime) 
{ 
	if(m_pParent)
	{
		if(!m_pParent->m_bIsStatic)
		{
			m_bIsStatic = 0;
		}
	}

	if(!m_bIsChanged)
	{
		VSAVObject * pParent = m_pParent;
		while(pParent && !pParent->m_bIsChanged)
		{
			pParent = pParent->m_pParent;
		}
		if (pParent)
		{
			m_bIsChanged = true;
		}
		else
		{
			return ;
		}
	}



	
	if(m_pParent) 
	{
		m_World.Product(m_Local,m_pParent->m_World);

	}
	else 
		m_World = m_Local; 
	
	
	/*updateNodeController*/

} 

void VSAVObject::GetLocalDir(VSVector3 &Dir,VSVector3 &Up,VSVector3 & Right)const
{
	m_Local.GetDir(Dir,Up,Right);
}
void VSAVObject::GetWorldDir(VSVector3 &Dir,VSVector3 &Up,VSVector3 & Right)
{
	m_World.GetDir(Dir,Up,Right);
}
const VSVector3 & VSAVObject::GetWorldScale()
{
	return m_World.GetScale();
}
const VSVector3 & VSAVObject::GetWorldTranslate()
{
	return m_World.GetTranslate();
}
const VSMatrix3X3 & VSAVObject::GetWorldRotate()
{
	return m_World.GetRotate();
}
const VSTransform & VSAVObject::GetWorldTransform()
{
	m_World.GetCombine();
	return m_World;
}
void VSAVObject::SetLocalTransform(const VSTransform & LocalTransform)
{
	m_bIsChanged = true;
	m_Local = LocalTransform;
}
void VSAVObject::SetLocalMat(const VSMatrix3X3W VSMat)
{
	m_bIsChanged = true;
	m_Local.SetMatrix(VSMat);
}
void VSAVObject::SetLocalScale(const VSVector3 & fScale)
{
	m_bIsChanged = true;
	m_Local.SetScale(fScale);

}
void VSAVObject::SetLocalTranslate(const VSVector3& Translate)
{
	m_bIsChanged = true;
	m_Local.SetTranslate(Translate);

}
void VSAVObject::SetLocalRotate(const VSMatrix3X3 & Rotate)
{
	m_bIsChanged = true;
	m_Local.SetRotate(Rotate);

}